home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 6 / FM Towns Free Software Collection 6.iso / t_os / book / src / file.c < prev    next >
C/C++ Source or Header  |  1993-07-08  |  9KB  |  338 lines

  1. #include    <stdio.h>
  2. #include    <stdlib.h>
  3. #include    <string.h>
  4. #include    <string.h>
  5. #include    <ctype.h>
  6. #include    <egb.h>
  7. #include    <mos.h>
  8. #include    "oaklib.h"
  9. #include    "file.h"
  10. #include    "menu_evt.h"
  11. #include    "init.h"
  12. #include    "book.h"
  13. #include    "lib.h"
  14. #include    "menu.h"
  15.  
  16.         LBLOCK *base[LINEBLOCKs] ;  /*  行ブロックを指すポインタの配列  */
  17. #if 0
  18. static  char    *filebuf = NULL ;   /*  生のファイルデータ  */
  19. static  char    *ptr = NULL ;       /*  データ処理用のワーク  */
  20. static  int     readpos = 0L ;      /*  データ処理用のワーク  */
  21. static  int     fsize = 0L ;        /*  現在ファイルの大きさ  */
  22. static  HEADER  filehead = {NULL} ; /*  ファイルヘッダ  */
  23.  
  24. static  int     now_block = -1 ;    /*  base[]をどこまで使っているか  */
  25. static  int     now_line = 0 ;      /*  現在ファイルの行数  */
  26. static  int     now_linelow = 0 ;   /*  現在ファイルの行数 % LINEPTRs  */
  27. #endif
  28. static  FILE    *file_ptr = NULL ;
  29.  
  30. typedef struct  {
  31.     char    *filebuf ;      /*  生のファイルデータ  */
  32.     char    *ptr ;          /*  データ処理用のワーク  */
  33.     int     readpos ;       /*  データ処理用のワーク  */
  34.     int     fsize ;         /*  ファイルの大きさ  */
  35.     int     readsize ;      /*  ファイルを読み込んだ量  */
  36.     int     readstep ;      /*  分割読み込みする量  */
  37.     HEADER  filehead ;      /*  ファイルヘッダ  */
  38.  
  39.     int     now_block ;     /*  base[]をどこまで使っているか  */
  40.     int     now_line ;      /*  現在ファイルの行数  */
  41.     int     now_linelow ;   /*  現在ファイルの行数 % LINEPTRs  */
  42. }   HEAD ;
  43.  
  44. static  HEAD    head = { NULL, NULL, 0L,0L,0L,0L, {NULL}, -1, 0, 0 } ;
  45.  
  46.  
  47. /*
  48.  *  渡されたパラメータを行管理テーブルにセットする
  49. */
  50. static  int     set_linedata( char *str, int bytes )
  51. {
  52.     static  LBLOCK  *bp = NULL ;
  53.  
  54.     if( ++head.now_linelow >= LINEPTRs )
  55.     {
  56.         if( ( bp = malloc( sizeof( LBLOCK ) ) ) == NULL )
  57.             return ERROR ;
  58.         if( ++head.now_block >= LINEBLOCKs )
  59.             return ERROR ;
  60.         base[head.now_block] = bp ;
  61.         head.now_linelow = 0 ;
  62.     }
  63.  
  64.     bp->ptr[head.now_linelow].buf = str ;
  65.     bp->ptr[head.now_linelow].bytes = bytes ;
  66.     head.now_line++ ;
  67.  
  68.     return ERROR+1 ;
  69. }
  70.  
  71. void    backup_file( back_t flag )
  72. {
  73.     static  back_t  status = RESTORE ;
  74.     static  HEAD    tmp_head ;
  75.     static  LBLOCK *tmp_base[LINEBLOCKs] ;
  76.             int     i ;
  77.  
  78.     switch( flag )
  79.     {
  80.       case BACKUP:  /*  バックアップして、表向きは初期化  */
  81.         status = BACKUP ;
  82.         tmp_head = head ;
  83.         for( i = 0 ; i < LINEBLOCKs ; i++ )
  84.             tmp_base[i] = base[i] ;
  85.         head.now_block = -1 ;
  86.  
  87.         head.filehead.file = NULL ;
  88.         head.filebuf = NULL ;
  89.         break ;
  90.  
  91.       case RESTORE: /*  backupしてある時だけ  */
  92.         if( status == BACKUP ) /*  backupしてある時だけ  */
  93.         {
  94.             status = RESTORE ;
  95.             head = tmp_head ;
  96.             *base = *tmp_base ;
  97.         }
  98.         break ;
  99.  
  100.       case INIT:    /*  初期化してしまう  */
  101.         status = RESTORE ;
  102.         break ;
  103.     }
  104. }
  105.  
  106. void    free_head( void )
  107. {
  108.     int     i ;
  109.  
  110.     /*  行管理ブロックを開放  */
  111.     for( i = 0 ; i <= head.now_block ; i++ )
  112.         free( base[i] ) ;
  113.     head.now_block = -1 ;
  114.  
  115.     /*  ファイルヘッダのファイル名バッファを開放  */
  116.     if( head.filehead.file != NULL )
  117.         free( head.filehead.file ), head.filehead.file = NULL ;
  118. }
  119.  
  120.  
  121. /* #define beof() (head.readpos > head.fsize)  *//*  eof?  */
  122. static  int     read_file( void )
  123. {
  124.     const   readstep = 62 * 1024 ;  /*  62KB ずつ読む  */
  125.     int     size, status = 0 ;
  126.  
  127.     if( ( size = head.fsize - head.readsize ) > 0 && file_ptr != NULL )
  128.     {
  129.         if( size > readstep )
  130.             size = readstep ;
  131.         status = fread( &head.filebuf[head.readsize], 1,size, file_ptr ) ;
  132.         head.readsize += status ;
  133.         head.filebuf[head.readsize] = '\0' ;   /*  ファイル末尾に \0 を追加  */
  134.     }
  135.  
  136.     return status ;
  137. }
  138. static  int     beof( void )
  139. {
  140.     if( head.readpos > head.readsize ) /*  eof?  */
  141.     {
  142.         if( head.fsize > head.readsize )
  143.         {
  144.             read_file() ;
  145.             return FALSE ;
  146.         }
  147.         return TRUE ;
  148.     }
  149.     return FALSE ;
  150. }
  151.  
  152. static  int     read_line( void )
  153. {
  154.     int     i, j, bytes ;
  155.     char    *p ;
  156.  
  157.     bytes = head.readpos ;
  158.  
  159.     for( p=head.ptr, i=0 ; i < LINEMAX ; p++, i++ )
  160.     {
  161.         head.readpos++ ;
  162.         if( beof() )  /*  eof?  */
  163.             break ;
  164.  
  165.         if( israw( *p ) )           /*  そのまま  */
  166.             ;
  167.         else if( iskanji( *p ) )    /*  全角文字  */
  168.         {
  169.             if( i == ( LINEMAX - 1 ) )
  170.             {
  171.                 head.readpos-- ;
  172.                 break ;
  173.             }
  174.  
  175.             /*  全角文字の2バイト目を獲得  */
  176.             if( beof() )
  177.                 break ;
  178.  
  179.             if( iskanji2( *(p+1) ) )
  180.             {
  181.                 p++, head.readpos++, i++ ;
  182.             }
  183.         }
  184.         else if( isctrl( *p ) )     /*  制御コード  */
  185.         {
  186.             if( *p == '\x0D' )      /*  リターンコード  */
  187.             {
  188.                 head.readpos++, p+=2 ;
  189.                 if( !beof() && *(p-1) == '\x0A' )
  190.                     break ;
  191.                 head.readpos--, p-=2 ;
  192.             }
  193.  
  194.             if( *p == '\t' && setup.tabsiz > 0 )     /*  タブ  */
  195.             {
  196.                 j = setup.tabsiz - ( i % setup.tabsiz ) ;
  197.                 while( i < LINEMAX && j-- > 0 )
  198.                     i++ ;
  199.                 i-- ;
  200.             }
  201.             else if( setup.disp_ctrl )          /*  一般制御コード  */
  202.             {
  203.                 if( i == ( LINEMAX - 1 ) )
  204.                 {
  205.                     head.readpos-- ;
  206.                     break ;
  207.                 }
  208.                 else
  209.                     i++ ;
  210.             }
  211.         }
  212.     }
  213.  
  214.     bytes = head.readpos - bytes ;
  215.     if( beof() )  /*  eof?  */
  216.         bytes-- ;
  217.  
  218.     if( i > 0 || !beof() )
  219.         j = set_linedata( head.ptr, bytes ) ;
  220.     else
  221.         j = ERROR ;
  222.     head.ptr = p ;
  223.  
  224.     return j ;
  225. }
  226.  
  227. static  int     get_max_memory( int size )
  228. {
  229.     const   int     step = 128 * 1024 ;     /*  128KBytes step  */
  230.             char   *buf = NULL ;
  231.  
  232.     while( size > 0 )
  233.     {
  234.         size -= step ;
  235.         if( ( buf = malloc( size ) ) != NULL )
  236.             break ;
  237.     }
  238.  
  239.     if( buf != NULL )
  240.     {
  241.         free( buf ) ;
  242.         if( (size -= step) > 0 )
  243.             return size ;
  244.     }
  245.  
  246.     return 0 ;
  247. }
  248. static  void    mem_err( char *msg, int a, int b )
  249. {
  250.     char    buf[80] ;
  251.  
  252.     strcpy( buf, msg ) ;
  253.     strcat( buf, " [" ) ;
  254.     strcat( buf, formdigitL( a>>10, 1, OFF ) ) ;
  255.     strcat( buf, "KB / " ) ;
  256.     strcat( buf, formdigitL( b>>10, 1, OFF ) ) ;
  257.     strcat( buf, "KB]" ) ;
  258.     report_fatal_error( ERR_FILE, buf ) ;
  259. }
  260.  
  261.  
  262. HEADER  *read_sub( char *file, readtype_t reform )
  263. {
  264.     FILE    *fp = NULL ;
  265.     char    *p ;
  266.     int     org_fsize ;
  267.  
  268.     if( head.filehead.file != NULL )   /*  開放されてない  */
  269.         free_head() ;
  270.  
  271.     head.now_block = -1, head.now_line = 0, head.now_linelow = LINEPTRs ;
  272.     file_ptr = NULL ;
  273.  
  274.     if( reform == FILE_REFORM && head.filebuf != NULL )  /*  タブサイズ変更  */
  275.         ;
  276.     else
  277.     {
  278.         head.readsize = 0 ;
  279.  
  280.         if( ( fp = fopen( file, "rb" ) ) == NULL )
  281.         {
  282.             report_fatal_error( ERR_FILE, "オープンに失敗" ) ;
  283.             return NULL ;
  284.         }
  285.         file_ptr = fp ;
  286.  
  287.         head.fsize = org_fsize = get_fsize( fp ) ;
  288.         if( head.fsize > 1024 && reform == FILE_PREVIEW )
  289.             head.fsize = 1024 ;
  290.  
  291.         if( head.filebuf != NULL )
  292.             free( head.filebuf ) ;
  293.         if( ( head.filebuf = malloc( (size_t)head.fsize+1 ) ) == NULL )
  294.         {
  295.             if( ( head.fsize = get_max_memory( head.fsize ) ) < 1 ||
  296.                 ( head.filebuf = malloc( (size_t)head.fsize+1 ) ) == NULL )
  297.             {
  298.                 fclose( fp ) ;
  299.                 report_fatal_error( ERR_FILE, "メモリ不足" ) ;
  300.                 return NULL ;
  301.             }
  302.  
  303.             mem_err( "ファイル全体が読めない", head.fsize, org_fsize ) ;
  304.         }
  305.         fseek( fp, 0L, SEEK_SET ) ;
  306.     }
  307.     head.readpos = 0 ;
  308.     head.ptr = head.filebuf ;     /*  ファイルデータの開始位置  */
  309.  
  310.     /*  ファイルヘッダのデータを初期化  */
  311.     head.filehead.file = strdup( file ) ;
  312.     if( ( p = jstrrchr( head.filehead.file, '\\' ) ) == NULL &&
  313.         ( p = strchr( head.filehead.file, ':' ) ) == NULL )
  314.         head.filehead.name = head.filehead.file ;
  315.     else
  316.         head.filehead.name = p + 1 ;
  317.     head.filehead.cur_pos = head.filehead.line_now =
  318.     head.filehead.line_max = head.filehead.line_num = 0 ;
  319.  
  320.     /*  ファイルのデータを参照して行管理テーブルにセット  */
  321.     if( set_linedata( "", 0 ) != ERROR )    /*  最初の番兵  */
  322.         while( read_line() != ERROR ) ;
  323.     while( read_file() > 0 ) ;  /*  ファイルの読み込みは最後までやる  */
  324.  
  325.     /*  ファイルの末端に届いているかどうか  */
  326.     if( ( !beof() || head.now_line < 1 ) && reform != FILE_PREVIEW )
  327.         mem_err( "ファイル全体を整形できない", head.readpos, head.fsize ) ;
  328.  
  329.     set_linedata( "", 0 ) ; /*  最後の番兵  */
  330.     head.filehead.line_max = head.now_line - 1 ;
  331.  
  332.     if( fp != NULL )
  333.         fclose( fp ) ;
  334.  
  335.     return &head.filehead ;
  336. }
  337.  
  338.